﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Data;
using System.Collections;

namespace GlobalTracker.WebService
{
  /// <summary>
  /// Web service utilizado para prover comunicação entre as aplicações Global Tracker Location e Global Tracker Web.
  /// 
  /// Ela foi criada para satisfazer diretamente os casos de uso:
  /// - W10: Interagir com Banco de Dados da Web
  /// - M11: Interagir com Banco de Dados da Web
  /// 
  /// Todos os demais casos de uso também necessitam deste Web Service indiretamente.
  /// </summary>
  [WebService(Namespace = "http://tempuri.org/")]
  [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
  [System.ComponentModel.ToolboxItem(false)]
  // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
  // [System.Web.Script.Services.ScriptService]
  public class GeneralService : System.Web.Services.WebService
  {

    /// <summary>
    /// Este método é utilizado para verificar se as coordenadas enviadas pelo dispositivo móvel ultrapassou o perímetro delimitado pela cerca eletrônica.
    /// </summary>
    /// <param name="identificador">Código ou expressão a ser validada.</param>
    /// <param name="latitude">Latitude a ser avaliada.</param>
    /// <param name="longitude">Longitude a ser avaliada</param>
    /// <param name="imei">Código universal do dispositivo</param>
    /// <returns>Retorna se o dispositivo ultrapassou o limite.</returns>
    [WebMethod]
    public bool UltrapassouCercaEletronica(string identificador, string latitude, string longitude, string imei)
    {
      Core.DatabaseAccess databaseAccess = new Core.DatabaseAccess();
      try
      {
        // Estabelece conexão com o banco de dados.
        databaseAccess.Connect();
        string cercaEletronica = databaseAccess.GetDataToString("SELECT LISTALATITUDELONGITUDE FROM CERCAELETRONICA WHERE IMEI = '" + imei + "'"); // Recupera limites da cerca.
        string[] retornoArray = cercaEletronica.Split('#');
        float[] arrayLatitude = new float[retornoArray.Length - 1]; //Cria array para coordenadas de Latitude. (Eixo Y)
        float[] arrayLongitude = new float[retornoArray.Length - 1]; //Cria array para coordenadas de Longitude. (Eixo X)
        float fLatitude = System.Convert.ToSingle(latitude); // Latidude a ser avaliada com o tipo float.
        float fLongitude = System.Convert.ToSingle(longitude); // Longitude a ser avaliada com o tipo float.
        bool dentroDaCerca = false; // Variável de controle para determinar se esta dentro da cerca.

        // Preenche os arrays de latitude e longitude.
        for (int i = 0; i < retornoArray.Length; i++)
        {
          if ((retornoArray[i].ToString().Trim().Length - 1) > 0)
          {
            arrayLatitude[i] = System.Convert.ToSingle(retornoArray[i].ToString().Substring(0, retornoArray[i].ToString().IndexOf(";")).Replace(".", ","));
            arrayLongitude[i] = System.Convert.ToSingle(retornoArray[i].ToString().Substring(retornoArray[i].ToString().IndexOf(";") + 1).Replace(".", ","));
          }
        }

        // Variavel j, utilizada para avaliar o ponto anterior do período.
        int j = (arrayLatitude.Length - 1);

        // Avalia se o ponto em questão esta dentro do polígono, baseado na ideia de que a latitude do mesmo deve possuir quantidade ímpar de lados do polígono à sua direita e esquerda.
        for (int i = 0; i < arrayLatitude.Length; i++)
        {
          if (arrayLatitude[i] < fLatitude && arrayLatitude[j] >= fLatitude ||
            arrayLatitude[j] < fLatitude && arrayLatitude[i] >= fLatitude)
          {
            if (arrayLongitude[i] + (fLatitude - arrayLatitude[i]) / (arrayLatitude[j]-arrayLatitude[i]) * (arrayLongitude[j]-arrayLongitude[i]) < fLongitude)
            {
              dentroDaCerca = !dentroDaCerca;
            }
          }
          j = i;
        }
        return !dentroDaCerca;
      }
      catch
      {
        databaseAccess.Disconnect();
        databaseAccess = null;
        GC.Collect();
        return false;
      }
      finally
      {
        databaseAccess.Disconnect();
        databaseAccess = null;
        GC.Collect();
      }          
    }

    /// <summary>
    /// APENAS PARA TESTES - Este método é utilizado para verificar se as coordenadas enviadas pelo dispositivo móvel ultrapassou o perímetro delimitado pela cerca eletrônica.
    /// </summary>
    /// <param name="identificador">Código ou expressão a ser validada.</param>
    /// <param name="latitude">Latitude a ser avaliada.</param>
    /// <param name="longitude">Longitude a ser avaliada</param>
    /// <param name="imei">Código universal do dispositivo</param>
    /// <returns>Retorna string dos testes realizados.</returns>
    [WebMethod]
    public string UltrapassouCercaEletronicaStr(string identificador, string latitude, string longitude, string imei)
    {
      string s = string.Empty;
      Core.DatabaseAccess databaseAccess = new Core.DatabaseAccess();
      try
      {
        databaseAccess.Connect();
        string cercaEletronica = databaseAccess.GetDataToString("SELECT LISTALATITUDELONGITUDE FROM CERCAELETRONICA WHERE IMEI = '" + imei + "'");
        string[] retornoArray = cercaEletronica.Split('#');
        float[] arrayLatitude = new float[retornoArray.Length - 1]; //Y
        float[] arrayLongitude = new float[retornoArray.Length - 1]; //X
        float fLatitude = System.Convert.ToSingle(latitude);
        float fLongitude = System.Convert.ToSingle(longitude);
        bool dentroDaCerca = false;

        s = "Latitude/Longitude<br>";
        s += latitude+"/" + longitude + "<br>";
        s += "Array Latitude e Longitude<br>";
        

        for (int i = 0; i < retornoArray.Length; i++)
        {
          if ((retornoArray[i].ToString().Trim().Length - 1) > 0)
          {
            arrayLatitude[i] = System.Convert.ToSingle(retornoArray[i].ToString().Substring(0, retornoArray[i].ToString().IndexOf(";")).Replace(".", ","));
            arrayLongitude[i] = System.Convert.ToSingle(retornoArray[i].ToString().Substring(retornoArray[i].ToString().IndexOf(";") + 1).Replace(".", ","));

            s += arrayLatitude[i].ToString() + "/" + arrayLongitude[i].ToString() + "<br>"; 
          }
        }

        int j = (arrayLatitude.Length - 1);

        s += "Testes<br>";

        for (int i = 0; i < arrayLatitude.Length; i++)
        {
          s += "if (" +  arrayLatitude[i].ToString() + " < " + latitude + " && " + arrayLatitude[j].ToString() + " >= " + latitude + " || " + arrayLatitude[j].ToString() + " < " + latitude + " && " + arrayLatitude[i].ToString() + " >= " + latitude + ")<br>"; 

          if (arrayLatitude[i] < fLatitude && arrayLatitude[j] >= fLatitude ||
            arrayLatitude[j] < fLatitude && arrayLatitude[i] >= fLatitude)
          {
            s += "if (" + arrayLongitude[i].ToString()+" + (" + latitude + " - " + arrayLatitude[i].ToString() + ") / (" + arrayLatitude[j].ToString() +" - " + arrayLatitude[i].ToString() + ") * (" + arrayLongitude[j].ToString()+" - " + arrayLongitude[i].ToString()+") < " + longitude + ")<br>";
            if (arrayLongitude[i] + (fLatitude - arrayLatitude[i]) / (arrayLatitude[j] - arrayLatitude[i]) * (arrayLongitude[j] - arrayLongitude[i]) < fLongitude)
            {
              s += "OK;<br>";
              dentroDaCerca = !dentroDaCerca;
            }
          }
          j = i;
        }
        return s;
      }
      catch
      {
        databaseAccess.Disconnect();
        databaseAccess = null;
        GC.Collect();
        return string.Empty;
      }
      finally
      {
        databaseAccess.Disconnect();
        databaseAccess = null;
        GC.Collect();
      }
    }

    /// <summary>
    /// Este método será implementado para funcionar como um validodar de chave pública e chave privada,
    /// para que nenhuma aplicação não autorizada consiga utilizar este Web Service.
    /// </summary>
    /// <param name="identificador">Código ou expressão a ser validada.</param>
    /// <returns>Retorna true se correto e false se incorreto.</returns>
    private bool ValidarIdentificador(string identificador)
    {
      return true; // Validação não implementada, sempre retorna true.
    }

    /// <summary>
    /// Método utilizado para realizar teste de conexão.
    /// </summary>
    /// <returns>Retorna true se conectado, caso contrário false.</returns>
    [WebMethod]
    public string TesteConexao()
    {
      Core.DatabaseAccess databaseAccess = new Core.DatabaseAccess(); ;
      return databaseAccess.ConnectTest();
    }

    /// <summary>
    /// Método utilizado para realizar autenticação de um usuário administrador.
    /// </summary>
    /// <param name="identificador">Chave de validação.</param>
    /// <param name="login">Usuário utilizado para autenticação.</param>
    /// <param name="senha">Senha utilizada para autenticação.</param>
    /// <returns>Retorna true caso a autenticação seja positiva e false caso negativa.</returns>
    [WebMethod]
    public bool AutenticacaoUsuarioAdministrador(string identificador, string login, string senha)
    {
      if (!ValidarIdentificador(identificador))
        return false;

      Core.DatabaseAccess databaseAccess = new Core.DatabaseAccess();

      try
      {
        databaseAccess.Connect();
        int count = 0;
        // Realiza consulta na tabela de usuário e retorna 1 caso exista usuário e 0 caso não exista.
        int.TryParse(databaseAccess.GetDataToString("SELECT COUNT(*) FROM USUARIO WHERE LOGIN = '" + login + "' AND SENHA = '" + senha + "'"), out count);


        if (count == 0)
          return false;
        else
          return true; 
      }
      catch
      {
        databaseAccess.Disconnect();
        databaseAccess = null;
        GC.Collect();
        return false;
      }
      finally
      {
        databaseAccess.Disconnect();
        databaseAccess = null;
        GC.Collect();        
      }    
    }

    /// <summary>
    /// Método utilizado para alterar senha do usuário Administrador.
    /// </summary>
    /// <param name="identificador">Chave de Validação</param>
    /// <param name="login">Usuário utilizado para autenticação.</param>
    /// <param name="senhaAntiga">Senha utilizada para autenticação.</param>
    /// <param name="novaSenha">Nova senha que será utilizada para autenticação.</param>
    /// <returns>Retorna true caso a operação tenha obtido sucesso e false caso tenha falhado.</returns>
    [WebMethod]    
    public bool AlterarSenhaUsuarioAdministrador(string identificador, string login, string senhaAntiga, string novaSenha)
    {
      if (!ValidarIdentificador(identificador))
        return false;

      Core.DatabaseAccess databaseAccess = new Core.DatabaseAccess(); ;

      try
      {
        databaseAccess.Connect();
        int count = 0;
        // Realiza alteração da senha e retorna 1 caso exista a alteração tenha sido realizada e 0 caso contrário.
        int.TryParse(databaseAccess.ExecuteCommand("UPDATE USUARIO SET SENHA = '" + novaSenha + "' WHERE LOGIN = '" + login + "' AND SENHA = '" + senhaAntiga + "'"), out count);

        if (count == 0)
          return false;
        else
          return true;
      }
      catch
      {
        databaseAccess.Disconnect();
        databaseAccess = null;
        GC.Collect();
        return false;
      }
      finally
      {
        databaseAccess.Disconnect();
        databaseAccess = null;
        GC.Collect();
      }    
    }

    /// <summary>
    /// Método utilizado para inserir um dispositivo móvel no sistema.
    /// </summary>
    /// <param name="identificador">Chave de Validação</param>
    /// <param name="imei">Código universal do dispositivo</param>
    /// <param name="senha">Senha que será utilizada para autenticação</param>
    /// <param name="nome">Nome do Proprietário</param>
    /// <param name="email">E-Mail do proprietário</param>
    /// <param name="sistemaOperacional">Versão do sistema operacional</param>
    /// <param name="intervaloMonitoramento">Intervalo para envio das coordenadas</param>
    /// <returns></returns>
    [WebMethod]
    public bool InserirDispostivoMovel(string identificador, string imei, string senha, string nome, string email, string sistemaOperacional, float intervaloMonitoramento)
    {
      if (!ValidarIdentificador(identificador))
        return false;

      Core.DatabaseAccess databaseAccess = new Core.DatabaseAccess(); ;

      try
      {
        databaseAccess.Connect();
        int count = 0;
        // Realiza inserção do dispositivo móvel e retorna 1 caso tenha obtido sucesso e 0 caso contrário.
        int.TryParse(databaseAccess.ExecuteCommand("INSERT INTO DISPOSITIVOMOVEL (IMEI, SENHA, NOME, EMAIL, SISTEMAOPERACIONAL, INTERVALOMONITORAMENTO)\r\n"+
          "VALUES ('" + imei + "', '" + senha + "', '" + nome + "','" + email + "', '" + sistemaOperacional + "', " + intervaloMonitoramento.ToString().Replace(",", ".") + ")"), out count);

        if (count == 0)
          return false;
        else
          return true;
      }
      catch
      {
        databaseAccess.Disconnect();
        databaseAccess = null;
        GC.Collect();
        return false;
      }
      finally
      {
        databaseAccess.Disconnect();
        databaseAccess = null;
        GC.Collect();
      }    
    }

    /// <summary>
    /// Método utilizado para realizar autenticação de um dispositivo móvel.
    /// </summary>
    /// <param name="identificador">Chave de validação.</param>
    /// <param name="login">IMEI utilizado para autenticação.</param>
    /// <param name="senha">Senha utilizada para autenticação.</param>
    /// <returns>Retorna true caso a autenticação seja positiva e false caso negativa.</returns>
    [WebMethod]
    public bool AutenticacaoDispositivoMovel(string identificador, string imei, string senha)
    {
      if (!ValidarIdentificador(identificador))
        return false;

      Core.DatabaseAccess databaseAccess = new Core.DatabaseAccess(); ;

      try
      {
        databaseAccess.Connect();
        int count = 0;
        int.TryParse(databaseAccess.GetDataToString("SELECT COUNT(*) FROM DISPOSITIVOMOVEL WHERE IMEI = '" + imei + "' AND SENHA = '" + senha + "'"), out count);

        if (count == 0)
          return false;
        else
          return true;
      }
      catch
      {
        databaseAccess.Disconnect();
        databaseAccess = null;
        GC.Collect();
        return false;
      }
      finally
      {
        databaseAccess.Disconnect();
        databaseAccess = null;
        GC.Collect();
      }

      return true;
    }

    /// <summary>
    /// Método utilizado para alterar senha de um dispositivo móvel.
    /// </summary>
    /// <param name="identificador">Chave de Validação</param>
    /// <param name="imei">Código universal do dispositivo móvel.</param>
    /// <param name="senhaAntiga">Senha utilizada para autenticação.</param>
    /// <param name="novaSenha">Nova senha que será utilizada para autenticação.</param>
    /// <returns>Retorna true caso a operação tenha obtido sucesso e false caso tenha falhado.</returns>
    [WebMethod]
    public bool AlterarSenhaDispositivoMovel(string identificador, string imei, string senhaAntiga, string novaSenha)
    {
      if (!ValidarIdentificador(identificador))
        return false;

      Core.DatabaseAccess databaseAccess = new Core.DatabaseAccess(); ;

      try
      {
        databaseAccess.Connect();
        int count = 0;
        int.TryParse(databaseAccess.ExecuteCommand("UPDATE DISPOSITIVOMOVEL SET SENHA = '" + novaSenha + "' WHERE IMEI = '" + imei + "' AND SENHA = '" + senhaAntiga + "'"), out count);

        if (count == 0)
          return false;
        else
          return true;
      }
      catch
      {
        databaseAccess.Disconnect();
        databaseAccess = null;
        GC.Collect();
        return false;
      }
      finally
      {
        databaseAccess.Disconnect();
        databaseAccess = null;
        GC.Collect();
      }    
    }

    /// <summary>
    /// Método utilizado para enviar as coordenadas geográficas e endereço para o banco de dados.
    /// </summary>
    /// <param name="identificador">Cahve de Validação</param>
    /// <param name="imei">Código universal do dispositivo móvel.</param>
    /// <param name="latitude">Latitude obtida</param>
    /// <param name="longitude">Longitude obtida</param>
    /// <param name="endereco">Endereço corresponde à coordenada</param>
    /// <returns>Retorna true caso a operação tenha obtido sucesso e false caso tenha falhado.</returns>
    [WebMethod]
    public bool InserirCoordenadasDispositivoMovel(string identificador, string imei, string latitude, string longitude, string endereco)
    {
      if (!ValidarIdentificador(identificador))
        return false;

      Core.DatabaseAccess databaseAccess = new Core.DatabaseAccess(); ;

      try
      {
        databaseAccess.Connect();
        int count = 0;
        int.TryParse(databaseAccess.ExecuteCommand("INSERT INTO COORDENADADISPOSITIVOMOVEL (IMEI, LATITUDE, LONGITUDE, ENDERECO, DATA)\r\n" +
          "VALUES ('" + imei + "', " + latitude.ToString().Replace(",", ".") + ", " + longitude.ToString().Replace(",", ".") + ",'" + endereco + "', GETDATE())"), out count);


        if(UltrapassouCercaEletronica(identificador, latitude, longitude, imei))
        {
          string emailOrigem = System.Configuration.ConfigurationManager.AppSettings["EmailOrigem"].ToString();
          string loginEmail = System.Configuration.ConfigurationManager.AppSettings["UsuarioEmail"].ToString();
          string senhaEmail = System.Configuration.ConfigurationManager.AppSettings["SenhaEmail"].ToString();
          string servidorEmail = System.Configuration.ConfigurationManager.AppSettings["ServidorSMTP"].ToString();
          string portaServidorEmail = System.Configuration.ConfigurationManager.AppSettings["PortaSMTP"].ToString();
          string emailDestinatario = databaseAccess.GetDataToString("SELECT EMAIL FROM DISPOSITIVOMOVEL WHERE IMEI = '" + imei + "'");

          databaseAccess.ExecuteCommand("INSERT INTO HISTORICOALERTA (IMEI, DATA, LATITUDE, LONGITUDE, ENDERECO) VALUES ('" + imei + "', GETDATE(), " + latitude.Replace(",", ".") + ", " + longitude.Replace(",", ".") + ", '" + endereco + "')");
          
          Core.EMail mail = new Core.EMail();
          mail.HasAuthentication = true;
          mail.Access = true;
          mail.EnableSSL = false;

          mail.SendMail("Alerta de violação de cerca eletrônica", "O dispositivo móvel identificado pelo IMEI " + imei + " ultrapassou o limite determinado para cerca eletrônica.<br>- Latitude: " + latitude + "<br>- Longitude: " + longitude, emailOrigem, emailDestinatario, servidorEmail, portaServidorEmail, loginEmail, senhaEmail);
        }

        if (count == 0)
          return false;
        else
          return true;
      }
      catch
      {
        return false;
      }
      finally
      {
        databaseAccess.Disconnect();
        databaseAccess = null;
        GC.Collect();
      }    
    }

    /// <summary>
    /// Método utilizado para persistir as configurações de cerca eletronica no banco de dados
    /// </summary>
    /// <param name="identificador">Chave de Validação</param>
    /// <param name="imei">Código universal do dispositivo móvel</param>
    /// <param name="permitePerimetroCerca">Consitir a permanência do dispositivo móvel dentro do perímetro</param>
    /// <param name="listaLatitudeLongitude">Lista de coordenadas geográficas que determinam o perímetro</param>
    /// <returns>Retorna true caso a operação tenha obtido sucesso e false caso tenha falhado.</returns>
    [WebMethod]
    public bool InserirCercaEletronica(string identificador, string imei, bool permitePerimetroCerca, string listaLatitudeLongitude)
    {
      if (!ValidarIdentificador(identificador))
        return false;

      Core.DatabaseAccess databaseAccess = new Core.DatabaseAccess(); ;
      string perimetro = "Sim";

      if (!permitePerimetroCerca)
        perimetro = "Não";

      try
      {
        databaseAccess.Connect();
        int count = 0;

        databaseAccess.ExecuteCommand("DELETE FROM CERCAELETRONICA WHERE IMEI = '"+ imei + "'");
        int.TryParse(databaseAccess.ExecuteCommand("INSERT INTO CERCAELETRONICA (IMEI, PERMITIRPERIMETROCERCA, LISTALATITUDELONGITUDE)\r\n" +
          "VALUES ('" + imei + "', '" + perimetro + "', '" + listaLatitudeLongitude + "')"), out count);

        if (count == 0)
          return false;
        else
          return true;
      }
      catch
      {
        databaseAccess.Disconnect();
        databaseAccess = null;
        GC.Collect();
        return false;
      }
      finally
      {
        databaseAccess.Disconnect();
        databaseAccess = null;
        GC.Collect();
      }   
    }

    /// <summary>
    /// Método utilizado para recuperar as coordenadas correspondentes a uma cerca eletrônica.
    /// </summary>
    /// <param name="identificador">Chave de Validação</param>
    /// <param name="imei">Código universal do dispositivo móvel</param>
    /// <returns>Retorna um Dataset contendo as coordenadas geográficas correspondentes à cerca eletrônica</returns>
    [WebMethod]
    public string[] RecuperarCercaEletronica(string identificador, string imei)
    {
      if (!ValidarIdentificador(identificador))
        return null;

      Core.DatabaseAccess databaseAccess = new Core.DatabaseAccess();

      try
      {
        databaseAccess.Connect();
        string retornoString = databaseAccess.GetDataToString("SELECT LISTALATITUDELONGITUDE FROM CERCAELETRONICA WHERE IMEI = '" + imei + "'");
        string[] retornoArray = retornoString.Split('#');

        return retornoArray;
      }
      catch
      {
        databaseAccess.Disconnect();
        databaseAccess = null;
        GC.Collect();
        return null;
      }
      finally
      {
        databaseAccess.Disconnect();
        databaseAccess = null;
        GC.Collect();
      } 
    }

    /// <summary>
    /// Método utilizado para excluir uma cerca eletrônica
    /// </summary>
    /// <param name="identificador">Chave de Validação</param>
    /// <param name="imei">Código universal do dispositivo móvel</param>
    /// <returns>Retorna true caso a operação tenha obtido sucesso e false caso tenha falhado.</returns>
    [WebMethod]
    public bool ExcluirCercaEletronica(string identificador, string imei)
    {
      if (!ValidarIdentificador(identificador))
        return false;

      Core.DatabaseAccess databaseAccess = new Core.DatabaseAccess(); ;
      
      try
      {
        databaseAccess.Connect();
        int count = 0;

        int.TryParse(databaseAccess.ExecuteCommand("DELETE INTO CERCAELETRONICA WHERE IMEI = '" + imei + "'"), out count);

        if (count == 0)
          return false;
        else
          return true;
      }
      catch
      {
        databaseAccess.Disconnect();
        databaseAccess = null;
        GC.Collect();
        return false;
      }
      finally
      {
        databaseAccess.Disconnect();
        databaseAccess = null;
        GC.Collect();
      }   
    }

    /// <summary>
    /// Método utilizado para retornar as coordenadas geográficas conforme os parâmetros passados.
    /// </summary>
    /// <param name="identificador">Chave de Validação</param>
    /// <param name="imei">Código universal do dispositivo móvel</param>
    /// <param name="quantidade">Quantidade de coletas a serem recuperadas</param>
    /// <returns>Retorna um DataSet contendo as coletas.</returns>
    [WebMethod]
    public DataSet RecuperarUltimasCoordenadasDispositivoMovel(string identificador, string imei, int quantidade)
    {
      if (!ValidarIdentificador(identificador))
        return null;

      Core.DatabaseAccess databaseAccess = new Core.DatabaseAccess(); ;

      try
      {
        databaseAccess.Connect();
        DataSet ds = databaseAccess.GetDataSet("SELECT TOP " + quantidade + " DATA, LATITUDE, LONGITUDE FROM COORDENADADISPOSITIVOMOVEL WHERE IMEI = '" + imei + "' ORDER BY DATA DESC");        
        return ds;
      }
      catch
      {
        databaseAccess.Disconnect();
        databaseAccess = null;
        GC.Collect();
        return null;
      }
      finally
      {        
        databaseAccess.Disconnect();
        databaseAccess = null;
        GC.Collect();
      } 
    }

    /// <summary>
    /// Método utilizado para retornar as coordenadas geográficas conforme os parâmetros passados.
    /// </summary>
    /// <param name="identificador">Chave de Validação</param>
    /// <param name="imei">Código universal do dispositivo móvel</param>
    /// <param name="dataInicial">Data de inicio das coordenadas</param>
    /// <param name="dataFinal">>Data de fim das coordenadas</param>
    /// <returns>Retorna um DataSet contendo as coletas.</returns>
    [WebMethod]
    public DataSet RecuperarCoordenadasPorPeriodoDispositivoMovel(string identificador, string imei, DateTime dataInicial, DateTime dataFinal)
    {
      if (!ValidarIdentificador(identificador))
        return null;

      Core.DatabaseAccess databaseAccess = new Core.DatabaseAccess(); ;

      try
      {
        databaseAccess.Connect();
        DataSet ds = databaseAccess.GetDataSet("SELECT DATA, LATITUDE, LONGITUDE FROM COORDENADADISPOSITIVOMOVEL WHERE IMEI = '" + imei + "' AND DATA BETWEEN #" + dataInicial + "# AND #" + dataFinal + "# ORDER BY DATA DESC");
        return ds;
      }
      catch
      {
        databaseAccess.Disconnect();
        databaseAccess = null;
        GC.Collect();
        return null;
      }
      finally
      {
        databaseAccess.Disconnect();
        databaseAccess = null;
        GC.Collect();
      }
    }

    /// <summary>
    /// Método utilizado para realizar consultas no banco de dados Microsoft SQL Server
    /// </summary>
    /// <param name="identificador">Chave de Validação</param>
    /// <param name="query">Query a ser executada</param>
    /// <returns></returns>
    [WebMethod]
    public DataSet RecuperarListagem(string identificador, string query)
    {
      if (!ValidarIdentificador(identificador))
        return null;

      Core.DatabaseAccess databaseAccess = new Core.DatabaseAccess(); ;

      try
      {
        databaseAccess.Connect();
        DataSet ds = databaseAccess.GetDataSet(query);
        return ds;
      }
      catch
      {
        databaseAccess.Disconnect();
        databaseAccess = null;
        GC.Collect();
        return null;
      }
      finally
      {        
        databaseAccess = null;
        GC.Collect();
      }
    }
  }
}